#include <memory>
#include "CommandBase.h"

//struct QCmdBase
bool QCmdBase::Decode(CInDataStream & ds)
{
    return QCmdBase::DecodeParam(ds) && DecodeParam(ds);
}

std::string QCmdBase::ToString() const
{
    return std::string("(") + QCmdBase::ToStringHelp() + ToStringHelp() + std::string(")");
}

std::string QCmdBase::ToStringHelp() const
{
    std::ostringstream oss;
    oss<<"(version_="<<version_
        <<",sign_="<<sign_
        <<",seq_="<<seq_
        <<",flag_="<<flag_
        <<",length_="<<length_
        <<",reserve_="<<Tools::DumpHex(reserve_,sizeof reserve_)
        <<",cmdtype_="<<CommandName(cmdtype_)
        <<")";
    return oss.str();
}

bool QCmdBase::DecodeParam(CInDataStream & ds)
{
    if(!(ds>>version_>>sign_>>seq_>>flag_>>length_))
        return false;
    ds.FetchData(reserve_,sizeof reserve_)>>cmdtype_;
    return sign_ == CMD_MAGIC && version_ == CMD_VERSION && ds;
}

//struct RCmdBase
RCmdBase::RCmdBase(int cmdtype)
    : version_(CMD_VERSION)
    , sign_(CMD_MAGIC)
    , seq_(0)
    , flag_(0)
    , cmdtype_(cmdtype)
{
    memset(reserve_,0,sizeof reserve_);
}

RCmdBase::RCmdBase(int cmdtype,const QCmdBase & qhead)
    : version_(qhead.version_)
    , sign_(qhead.sign_)
    , seq_(qhead.seq_)
    , flag_(qhead.flag_)
    , cmdtype_(cmdtype)
{
    memcpy(reserve_,qhead.reserve_,sizeof reserve_);
}

void RCmdBase::Encode(COutDataStream & ds) const
{
    size_t start = ds.Size();
    RCmdBase::EncodeParam(ds);
    EncodeParam(ds);
    ds.SetValue(start + LEN_OFFSET,U32(ds.Size() - start));
}

std::string RCmdBase::ToString() const
{
    return std::string("(") + RCmdBase::ToStringHelp() + ToStringHelp() + std::string(")");
}

std::string RCmdBase::ToStringHelp() const
{
    std::ostringstream oss;
    oss<<"(version_="<<version_
        <<",sign_="<<sign_
        <<",seq_="<<seq_
        <<",flag_="<<flag_
        <<",length_="<<length_
        <<",reserve_="<<Tools::DumpHex(reserve_,sizeof reserve_)
        <<",cmdtype_="<<QCmdBase::CommandName(cmdtype_)
        <<")";
    return oss.str();
}

void RCmdBase::EncodeParam(COutDataStream & ds) const
{
    ds<<version_<<sign_<<seq_<<flag_<<length_;
    ds.AppendData(reserve_,sizeof reserve_)<<cmdtype_;
}

